/*
 * Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
 *
 * Licensed under the Mulan PSL v2.
 * You can use this file according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of the License at
 *
 *     http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
 * FOR MORE DETAILS.
 */

#pragma once

#include <cstdint>
#include <fstream>
#include <memory>
#include <queue>
#include <vector>

#include "Utility/Configuration/SGParameter.h"

#include "DataStructure/Input/Solver/Subcase.h"

#include "Import/ImportAPI/Common/ImportExport.h"
#include "Import/ImportAPI/Common/ImportNamespace.h"
DBSERVICEFACTORY_DEC

SG_IMPORT_NAMESPACE_OPEN

/**
 * 导入Nastran模型文件
 */
class BDFImporter
{
  public:
    explicit BDFImporter (const std::shared_ptr<SG::DBManager::DBServiceFactory>& dbServiceFactory);
    ~BDFImporter ();

    /// @brief 读取文件
    /// @param szfile 文件路径
    /// @return 是否成功
    SG::DataStructure::Common::Status Load (const char* szfile);

  private:
    /// @brief 使用文件夹栈解析文件内的词条
    /// @param folderStack 文件夹栈
    /// @param iFile 文件流
    /// @return 是否成功
    bool ParseFile (std::vector<std::string> folderStack, std::queue<std::string>& iFile);

    /**
     * @brief 解析 include 词条，生成全文件路径
     *
     * @return IncludeState 返回值：
     *          INCLUDE_SUCCESS: include， 解析成功
     *          INCLUDE_FAIL: include，解析失败
     *          NOT_INCLUDE: 非 include
     */
    enum IncludeState : std::uint8_t
    {
        INCLUDE_SUCCESS,
        INCLUDE_FAIL,
        NOT_INCLUDE
    };
    IncludeState ParseInclude (std::vector<std::string> folderStack);

    /// @brief 解析PostBlock数据
    /// @return 是否成功
    bool ParsePostBlock ();

    /// @brief 单独解析PostBlock 中subcase相关内容
    /// @return 是否成功
    bool ParseCaseControl ();

    /// @brief 单独解析PostBlock Parameter相关内容
    /// @return 是否成功
    bool ParseParameter ();

    /**
     * @brief    检查lseq中sid和exciteid是否有重复
     *
     * @return   出现重复返回false
     * @author   wanglong
     * @date     2025.09.09
     */
    bool CheckLegalityLSEQ ();

    /// @brief 单独解析PostBlock ExecutiveSystemParameter相关内容
    bool ParseExecutiveSystemParameter ();
    /**
     * @brief 解析并处理全局 Subcase 设置。
     *
     * 该函数用于解析 `gloadSubcaseSet` 中的全局设置行，并将解析结果存储在 `global_subcase` 中。
     * 全局设置行可能包括 "SOL" 类型的行以及其他需要解析的条目。
     *
     * @param[out] global_subcase 用于存储解析后的全局 Subcase 信息。
     * @param[in] gloadSubcaseSet 包含全局 Subcase 设置的字符串集合，每个字符串代表一个设置条目。
     */
    static void ParseSingleCaseControl (SG::Utility::SGParameter& singleSubcase, std::vector<std::string>& singleSubcaseInfo);

    /// @brief 获取下一行
    /// @param StrLine
    /// @param File
    static void GetNextLine (std::queue<std::string>& File, _OUT std::string& StrLine);

    /// @brief 获取完整的一行 根据续行符号获取
    /// @param curLine
    /// @param File
    void GetCompleteLine (std::queue<std::string>& File, _OUT std::string& curLine);

    /// @brief 处理表格类型，续行是查看是否以ENDT结尾
    /// @param curLine
    /// @param File
    bool IsEndtContinue (std::string& str);

    /// @brief 是否继续向下读一行，用来判断当前这个是否是当前词条
    /// @param str 当前字符串
    /// @return
    static bool IsContinue (std::string& str);

    /**
     * @brief control块与bulk块会有重名key，判断当前completeLine是否是bulk Data
     *
     * @return bool 返回值：
     *          true：bulk Data
     *          false：control块
     */
    bool IsBulkDataLine ();

    /// @brief
    /// 更新m_CompleteLineKey的值，提取m_CompleteLine[0]的前8个字符，如果存在逗号,则保留逗号前字符（适应自由模式）去掉前后空格然后变为大写
    void UpdateCompleteLineKey (std::string& line);

    /// @brief
    /// 更新m_ControlKey的值，提取m_PostBlock[i]的Key去掉前后空格然后变为大写
    void UpdateControlKey (std::string& line);

    /**
     * @brief 将 m_PostBlock 分类为 SUBCASE、全局设置或其他行。
     *
     * 该函数用于遍历并解析传入的 BDF 文件行（EntryInfo），并将这些行分类为以下几类：
     * - **SUBCASE**：表示子案例的行，存储在 `allsubcase` 中，子案例定义通常在下一个 `SUBCASE` 或 `BEGIN BULK` 关键字之前。
     * - **全局设置**：即在解析字典中定义的条目，存储在 `gloadSubcaseSet` 中。
     * - **其他行**：不属于上述两类的行，存储在 `otherLine` 中。
     *
     * 解析过程对每行字符串进行预处理，包括将所有字符转换为大写，去除首尾空格，并根据行的关键字进行分类。
     *
     * @param[out] allsubcase 存储所有 SUBCASE 行（每个 SUBCASE 行是一个包含多行的 vector）。
     * @param[out] gloadSubcaseSet 存储全局解析设置的行。
     *
     */
    void ClassifyEntryInfo (std::vector<std::vector<std::string>>& allsubcase, std::vector<std::string>& gloadSubcaseSet);

    std::string m_CompleteLineKey;                                          ///< m_CompleteLine对应的key,转化为大写

    std::string m_ControlKey;                                               ///< 解析m_PostBlock line时记录的ControlKey,转化为大写

    std::vector<std::string> m_PostBlock;                                   ///< 非bulk Data词条解析的部分存储在这里

    std::vector<std::string> m_ParameterBlock;                              ///< 参数词条解析的部分存储在这里

    std::vector<std::string> m_ExecutiveSystemParameterBlock;               ///< Executive System Parameter Block解析的部分存储在这里

    std::vector<std::string> m_CompleteLine;                                ///< 每次获取的完整词条line

    std::shared_ptr<::SG::DBManager::DBServiceFactory> m_dbServiceFactory;  ///<  DBServiceFactory指针,调用该工厂创建的Service存储数据

    std::string m_foldPath;                                                 ///< Load加在文件的文件夹路径
    std::string m_fileName;                                                 ///< Load加在文件的文件名称
};

SG_IMPORT_NAMESPACE_CLOSE
